package com.cskaoyan.app.wxservice.impl;

import com.cskaoyan.app.bean.bo.WxRegisBO;
import com.cskaoyan.app.bean.bo.WxResetBO;
import com.cskaoyan.app.bean.po.MarketUser;
import com.cskaoyan.app.bean.po.MarketUserExample;
import com.cskaoyan.app.bean.vo.wx.WxAuthUserInfo;
import com.cskaoyan.app.bean.vo.wx.WxLoginDataVO;
import com.cskaoyan.app.config.AliComponent;
import com.cskaoyan.app.config.CaptchaManager;
import com.cskaoyan.app.exception.ValidationException;
import com.cskaoyan.app.mapper.MarketUserMapper;
import com.cskaoyan.app.shiro.CustomAuthToken;
import com.cskaoyan.app.shiro.LoginType;
import com.cskaoyan.app.util.EncryptUtil;
import com.cskaoyan.app.wxservice.WxAuthService;
import org.apache.shiro.SecurityUtils;
import org.apache.shiro.session.Session;
import org.apache.shiro.subject.Subject;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import java.util.Date;
import java.util.List;

@Service
public class WxAuthServiceImpl implements WxAuthService {

    @Autowired
    private MarketUserMapper userMapper;

    @Autowired
    private AliComponent aliComponent;

    @Autowired
    private CaptchaManager captchaManager;

    @Override
    public String getWxPass(String username) {
        List<MarketUser> users = searchUserByName(username);
        return users.stream().map(MarketUser::getPassword).findFirst()
                .orElse("");
    }

    @Override
    public MarketUser getWxUserByName(String username) {
        return searchUserByName(username).stream()
                .findFirst().orElse(new MarketUser());
    }

    @Override
    public void sendCaptcha(String mobile, int codeLen) throws ValidationException {
        if (!captchaManager.allow(mobile)) {
            throw new ValidationException("验证码间隔不可小于一分钟");
        }
        String code = captchaManager.add(mobile, codeLen);
        aliComponent.sendMsg(mobile, code);
    }

    @Override
    @Transactional
    public WxLoginDataVO register(WxRegisBO regisBO) throws ValidationException {
        String mobile = regisBO.getMobile();
        String code = regisBO.getCode();
        String username = regisBO.getUsername();
        String password = regisBO.getPassword();
        String realCode = captchaManager.get(mobile);
        if (!code.equals(realCode)) {
            throw new ValidationException("验证码不正确或已过期");
        }
        MarketUserExample example = new MarketUserExample();
        MarketUserExample.Criteria criteria1 = example.createCriteria();
        criteria1.andUsernameEqualTo(username).andDeletedEqualTo(false);
        MarketUserExample.Criteria criteria2 = example.createCriteria();
        criteria2.andMobileEqualTo(mobile).andDeletedEqualTo(false);
        example.or(criteria2);
        long existCnt = userMapper.countByExample(example);
        if (existCnt > 0) {
            throw new ValidationException("用户名或手机号已存在");
        }
        Subject subject = SecurityUtils.getSubject();
        Session session = subject.getSession();
        String host = session.getHost();
        Date accessTime = session.getLastAccessTime();
        MarketUser user = new MarketUser();
        String encrypt = EncryptUtil.encrypt(password);
        user.setUsername(username);
        user.setPassword(encrypt);
        user.setMobile(mobile);
        user.setGender((byte) 0);
        user.setNickname(username);
        user.setLastLoginIp(host);
        user.setLastLoginTime(accessTime);
        user.setAddTime(new Date());
        user.setUpdateTime(new Date());
        userMapper.insertSelective(user);
        subject.login(new CustomAuthToken(username, encrypt, LoginType.WX_PASSWD));
        Session loginSession = subject.getSession();
        loginSession.setAttribute("userid", user.getId());
        return new WxLoginDataVO((String) loginSession.getId(),
                new WxAuthUserInfo(username, ""));
    }

    @Override
    public void restPass(WxResetBO resetBO) throws ValidationException {
        String mobile = resetBO.getMobile();
        String password = resetBO.getPassword();
        String code = resetBO.getCode();
        String realCode = captchaManager.get(mobile);
        String encrypt = EncryptUtil.encrypt(password);
        if (!code.equals(realCode)) {
            throw new ValidationException("验证码不正确或已过期");
        }
        MarketUserExample example = new MarketUserExample();
        MarketUserExample.Criteria criteria = example.createCriteria();
        criteria.andMobileEqualTo(mobile).andDeletedEqualTo(false);
        MarketUser user = new MarketUser();
        user.setPassword(encrypt);
        int rows = userMapper.updateByExampleSelective(user, example);
        if (rows == 0) {
            throw new ValidationException("用户不存在");
        }
    }

    private List<MarketUser> searchUserByName(String username) {
        MarketUserExample userExample = new MarketUserExample();
        MarketUserExample.Criteria criteria = userExample.createCriteria();
        criteria.andUsernameEqualTo(username).andDeletedEqualTo(false);
        return userMapper.selectByExample(userExample);
    }
}
